package com.example.workflow;

//import org.camunda.bpm.ProcessEngineService;
//import com.alibaba.fastjson.JSONObject;
import org.camunda.bpm.engine.*;
import org.camunda.bpm.engine.history.HistoricActivityInstance;
import org.camunda.bpm.engine.history.HistoricTaskInstance;
import org.camunda.bpm.engine.impl.RepositoryServiceImpl;
import org.camunda.bpm.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.camunda.bpm.engine.impl.pvm.process.ActivityImpl;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.repository.ProcessDefinitionQuery;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.model.bpmn.Bpmn;
import org.h2.util.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import jakarta.annotation.Resource;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import java.io.*;
import java.util.*;

@RestController
@RequestMapping("/workflow")
public class CamundaController {
	@Autowired(required = false)
	private RepositoryService repositoryService;

	@Autowired(required = false)
	private RuntimeService runtimeService;

	@Autowired(required = false)
	private HistoryService historyService;

	@Autowired(required = false)
	private TaskService taskService;

	@Autowired(required = false)
	private IdentityService identityService;

	// 上传路径
//    @Value("${gx.camunda.upload}")
//    private String path ;
//    
	// 通用的工作流操作api服务类
//    @Resource
//    private ProcessEngineService processService ;

//    @PostMapping("/bpmn/upload")
//    public AjaxResult uploadFile(MultipartFile file, String fileName, String name) throws Exception {
//      try {
//        // 上传并返回新文件名称
//        InputStream is = file.getInputStream() ;
//        File storageFile = new File(path + File.separator + fileName) ;
//        FileOutputStream fos = new FileOutputStream(new File(path + File.separator + fileName)) ;
//        byte[] buf = new byte[10 * 1024] ;
//        int len = -1 ;
//        while((len = is.read(buf)) > -1) {
//          fos.write(buf, 0, len) ;
//        }
//        fos.close() ;
//        is.close() ;
//        // 创建部署流程
//        processService.getDefaultProcessEngine().
//        processService.createDeploy(fileName, name, new FileSystemResource(storageFile)) ;
//        return AjaxResult.success();
//      } catch (Exception e) {
//        return AjaxResult.error(e.getMessage());
//      }
//    }

	/**
	 * 查询已部署的流程定义列表
	 */
	@GetMapping("/deployed-cases")
	public List<String> getDeployedCases() {
		// and convert it to a list of WorkflowCase objects
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().list();
		return list.stream().map(e -> e.getId() + "," + e.getName() + "," + e.getVersion())
				.collect(Collectors.toList());
	}

	@GetMapping("/test")
	public List<String> getCases() {
		// and convert it to a list of WorkflowCase objects
//    	repositoryService.get
		List<String> ll = new ArrayList<String>();
		ll.add("Helloword");
		return ll;
	}

	@GetMapping("/diagram/{instanceId}")
	public List<String> getDiagram(@PathVariable(value = "instanceId") String instanceId) {
		// and convert it to a list of WorkflowCase objects

//    	repositoryService.getBpmnModelInstance("").getModel().getModelName();

		ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

		if (1 == processDefinitionQuery.count()) {
			ProcessDefinition processDefinition = processDefinitionQuery.singleResult();
//    	        InputStream expectedStream = new FileInputStream("d:/test.bpmn");

			System.out.println("processDefinition.getId()::" + processDefinition.getId());
			InputStream actualStream = repositoryService.getProcessModel(processDefinition.getId());

			try {
//    				File file =File.createTempFile("bpmn-model-api-",".bpmn");
				OutputStream os = new FileOutputStream("D:/test.bpmn");

//    				if(in.available())
				Long ret = actualStream.transferTo(os);

				System.out.println("ret::::::::::" + ret);

				os.flush();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

//    	        assertTrue(isEqual(expectedStream, actualStream));
		} else 
		{
			// some test diagrams do not contain executable processes
			// and are therefore ignored by the engine
		}
//    	}
//    	InputStream in = repositoryService.getProcessDiagram(instanceId);
//    	
//    	StringBuilder stringBuilder = new StringBuilder();
//    	
//    	
//    	

		List<String> ll = new ArrayList<String>();
		ll.add("Helloword");
		return ll;
	}

//    @ApiOperation("动态生成流程图")
	@GetMapping("/generateBPMN")
	public void autoGenerateBPMN() throws IOException {
//        BpmnModelInstance instance= Bpmn.createProcess()
//    	repositoryService.getProcessModel(null)
//    	
//                .startEvent()
//                .userTask()
//                .id("question")
//                .exclusiveGateway()
//                .name("Everything fine?")
//                .condition("yes","#{fine}")
//                .serviceTask()
//                .userTask()
//                .endEvent()
//                .moveToLastGateway()
//                .condition("no","#{!fine}")
//                .userTask()
//                .connectTo("question")
//                .done();
//        Bpmn.validateModel(instance);
//        File file =File.createTempFile("bpmn-model-api-",".bpmn");
//        Bpmn.writeModelToFile(file,instance);
	}

	/**
	 * 部署流程案例
	 *
	 * @param file BPMN文件
	 * @param name 流程名称
	 */
	@PostMapping("/deploy-case")
	public String deployCase(@RequestParam("file") MultipartFile file, @RequestParam("name") String name) {
		try (InputStream is = file.getInputStream()) {
			// 获取文件的名称
			String originalFilename = file.getOriginalFilename();

			Deployment deployment = repositoryService.createDeployment().addInputStream(originalFilename, is).name(name)
					.deploy();
			return deployment.getId();
		} catch (Exception e) {
			return e.getMessage();
		}
	}

	/**
	 * 启动流程实例
	 *
	 * @param caseId 流程定义id
	 */
	@PostMapping("/start-case/{caseId}")
	public String startCase(@PathVariable(value = "caseId") String caseId, @RequestBody String json) {

		Map map = new HashMap();
		if (json != null && !"".equals(json)) {
//            map = JSONObject.parseObject(json, Map.class);
		}
		// 部署流程
		ProcessInstance processInstance = runtimeService.startProcessInstanceById(caseId, map);
		return processInstance.getId();
	}

	/**
	 * 查询正在执行的任务列表
	 *
	 * @param caseId 流程实例id
	 */
	@GetMapping("/active-tasks")
	public List<String> getActiveTasks(@RequestParam(value = "caseId", required = false) String caseId) {
		List<Task> list = taskService.createTaskQuery().processInstanceId(caseId).list();
		// Implement the logic here
		return list.stream().map(e -> {
			return "任务id:" + e.getId() + ", 实例id:" + e.getProcessInstanceId() + ",流程定义id:" + e.getProcessDefinitionId();
		}).collect(Collectors.toList());
	}

	/**
	 * 审批通过任务
	 *
	 * @param taskId 任务id
	 * @param json   参数json字符串
	 */
	@PostMapping("/approve-task/{taskId}")
	public String approveTask(@PathVariable("taskId") String taskId, @RequestBody String json) {
		if (json != null && !"".equals(json)) {
//            Map map = JSONObject.parseObject(json, Map.class);

//            taskService.setVariables(taskId, map);
		}
		taskService.complete(taskId);
		return "Task approved successfully";
	}

	/**
	 * 查询历史流程案例列表
	 *
	 * @param caseId 流程实例id
	 */
	@GetMapping("/historical-cases")
	public List<HistoricTaskInstance> getHistoricalCases(
			@RequestParam(value = "caseId", required = false) String caseId) {
		List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(caseId)
				.list();
		return list;
	}

	/**
	 * 查询流程实例参数列表
	 *
	 * @param taskId 任务id
	 */
	@GetMapping("/task-variables")
	public Map<String, Object> getVariables(@RequestParam(value = "taskId", required = false) String taskId) {
		Map<String, Object> variables = taskService.getVariables(taskId);
		return variables;
	}

	/**
	 * 回退
	 *
	 * @param processInstanceId 流程实例id
	 */
	@PostMapping("/rollback/{instanceId}")
	public String rollback(@PathVariable("instanceId") String processInstanceId) {

		Task activeTask = taskService.createTaskQuery().processInstanceId(processInstanceId).active().singleResult();
		HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery().taskId(activeTask.getId())
				.singleResult();

		// 获取流程定义
		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(taskInstance.getProcessDefinitionId());

		// 获取当前活动
		ActivityImpl currentActivity = processDefinitionEntity.findActivity(taskInstance.getTaskDefinitionKey());

		// 获取起始活动
		List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
				.activityType("userTask").processInstanceId(processInstanceId).finished()
				.orderByHistoricActivityInstanceEndTime().desc().list();
		if (historicActivityInstances.size() == 0) {
			return "没有历史活动";
		}
		ActivityImpl lastActivity = processDefinitionEntity
				.findActivity(historicActivityInstances.get(0).getActivityId());

		// 退回至起点
		runtimeService.createProcessInstanceModification(processInstanceId)
				.cancelAllForActivity(currentActivity.getActivityId()).startBeforeActivity(lastActivity.getActivityId())
				.setAnnotation("退回").execute();
		return "Rollback successful";
	}

	/**
	 * 删除流程案例
	 *
	 * @param caseId 流程定义id
	 */
	@DeleteMapping("/delete-case/{caseId}")
	public String deleteCase(@PathVariable(value = "caseId") String caseId) {
		repositoryService.deleteProcessDefinition(caseId);
		return "successful";
	}

}
